///////////////////////////////////////////////////////////////////////////
// Copyright 2010 Arabic Game Developer Network, All rights reserved
// www.agd-online.com - info@agdn-online.com
//
// File: stateflow.h
// Description: High-level module for managing the flow of the game.
//
///////////////////////////////////////////////////////////////////////////

// This file is part of kvalleyX.
// 
// kvalleyX is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// kvalleyX is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with kvalleyX.  If not, see <http://www.gnu.org/licenses/>.

#ifndef _STATEFLOW_H
#define _STATEFLOW_H

/////////////////// #defines ///////////////////

#include <boost/ptr_container/ptr_map.hpp>
#include <boost/scoped_ptr.hpp>
#include <string>
#include "eventmanager.h"

namespace CoreLib
{

////////////////////////////////////////////////////////////////////
// Class: GameState
// Purpose: Base class from which states must derive in order to
//			support execution in the game.
////////////////////////////////////////////////////////////////////
class GameState
{
	private:
		std::string stateName;
	public:
		GameState() : stateName("GenericGameState") {}
		GameState(const std::string& name) : stateName(name) {}
		// Overrides
// 		virtual FlowAction Update(void) = 0;
		virtual void update(void) = 0;
		virtual void render(void) = 0;
// 		virtual bool TransitionAtEnd(void) { return true; }
		//virtual GameState& operator=(const GameState& right) = 0;
		virtual ~GameState() {}
};

class GameStateDescriptor
{
	private:
		std::string stateName;
		/// NOTE: other information may be added to describe a state.
	public:
		GameStateDescriptor(const std::string& name) : stateName(name) {};
		inline bool operator==(const GameStateDescriptor& right) const
		{
			return (stateName == right.stateName);
		}
		inline const std::string& getStateName() const
		{
			return stateName;
		}
};

class Transition
{
	private:
		boost::scoped_ptr<GameStateDescriptor> src;
		boost::scoped_ptr<GameStateDescriptor> dest;
	public:
		Transition(GameStateDescriptor* src, GameStateDescriptor* dest);
		inline const GameStateDescriptor* getSourceState() const;
		inline const GameStateDescriptor* getDestinationState() const;
};


////////////////////////////////////////////////////////////////////
// Class: StateFlow
// Purpose: High-level manager that executes the states and monitors
//			transitions between them.
////////////////////////////////////////////////////////////////////
class StateFlow
{
	private:
		/// TODO: replace GAME_FPS/2 with a time based value
// 		const static int kTransitionPeriod = 15;
		boost::scoped_ptr<GameState> currentState;
// 		int m_iTransitionTime;
// 		GameState::FlowAction m_eNextFlowAction;
		boost::ptr_multimap<StateEvent, Transition> transitions;

	public:
		static const char* START_STATE;

		StateFlow();
		virtual ~StateFlow();
		void update();
		void render(void);
		void start(void);
		void addTransition(GameStateDescriptor* src,
						   GameStateDescriptor* dest,
						   const StateEvent& event);
		virtual GameState* createState(
			const GameStateDescriptor& descriptor) const = 0;
		///TODO: add event handler/interface
};
} // CoreLib namespace

#endif // _STATEFLOW_H

////////////////// End of File : stateflow.h //////////////////